
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <lua.hpp>

void error (lua_State *L, const char *fmt, ...) {
	va_list argp;
	va_start(argp, fmt);
	vfprintf(stderr, fmt, argp);
	va_end(argp);
	lua_close(L);
	exit(EXIT_FAILURE);
}

void load_script (lua_State* L, const char *filename) {
	//if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) {
	//if (luaL_loadfile(L, filename)) {
	if (luaL_dofile(L, filename)) {
		error(L, "cannot run configuration file: %s", lua_tostring(L, -1));
	}
}


static void stackDump (lua_State *L) 
{
	int i;
	int top = lua_gettop(L);
	printf("\nStackDump ...\n");
	for (i = 1; i <= top; i++) { /* repeat for each level */
		printf("  #%d ", i);

		int t = lua_type(L, i);
		switch (t) {
			case LUA_TSTRING: /* strings */
				printf("`%s'", lua_tostring(L, i));
				break;
			case LUA_TBOOLEAN:   /* booleans */
				printf(lua_toboolean(L, i) ? "true" : "false");
				break;
			case LUA_TNUMBER: /* numbers */
				printf("%g", lua_tonumber(L, i));
				break;
			default: /* other values */
				printf("%s", lua_typename(L, t));
				break;
		}
		printf("\n"); /* put a separator */
	}
	printf("StackDump done.\n");      /* end the listing */
}



int
call_upcase(lua_State* L, int a, int b, const char* s, int* c, char* buf )
{
	lua_getglobal(L, "toupper");
	lua_pushnumber(L, a);
	lua_pushnumber(L, b);
	lua_pushlstring(L, s, strlen(s));

	int	rc = lua_pcall(L, 3, 3, 0);
	if (0 != rc) {
		error(L, "fail to toupper.\n");
	}

	stackDump( L );

	if (!lua_isnumber(L, -1)) {
		error(L, "toupper() must return length of string\n" );
	}
	int s_len = lua_tonumber(L, -1);

	if (!lua_isstring(L, -2)) {
		error(L, "toupper() must return an string\n" );
	}
	const char*	p = lua_tostring(L, -2);
	strcpy(buf, p);

	if (!lua_isnumber(L, -3)) {
		error(L, "toupper() must return an integer\n" );
	}
	*c = lua_tonumber(L, -3);

	lua_pop(L, 2);

	return 0;
}


#define	SCRIPT_FILENAME 	"upcase.lua"

int	main(void)
{

	lua_State *L = lua_open();
	luaL_openlibs( L );

	load_script( L, SCRIPT_FILENAME );

	int	a = 12, b=13, c=0;
	const char*	hello = "Hello, World.";
	char	buf[ 32 ];
	memset( buf, 0, sizeof(buf) );
	int	result = call_upcase( L, a, b, hello, &c, buf);
	fprintf(stderr, "call upcase(a=%d, b=%d, s='%s') return (%d, '%s')\n", a, b, hello, c, buf );

	return	0;
}

